package com.lzy.imagepicker.view;

import com.lzy.imagepicker.util.NumCalcUtil;
import com.lzy.imagepicker.util.ResUtil;
import com.lzy.imagepicker.util.Utils;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Image;
import ohos.agp.components.element.Element;
import ohos.agp.render.*;
import ohos.agp.utils.Color;
import ohos.agp.utils.Matrix;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayAttributes;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.media.image.ImagePacker;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Rect;
import ohos.multimodalinput.event.TouchEvent;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Optional;

/**
 * ================================================
 * 作    者：廖子尧
 * 版    本：1.0
 * 创建日期：2016/1/7
 * 描    述：
 * Matrix 的9个值分别为  缩放  平移  倾斜
 * MSCALE_X	 MSKEW_X	MTRANS_X
 * MSKEW_Y	 MSCALE_Y	MTRANS_Y
 * MPERSP_0  MPERSP_1	MPERSP_2
 * 修订历史：
 * ================================================
 */

public class CropImageView extends Image {

    /******************************** 中间的FocusView绘图相关的参数 *****************************/
    public enum Style {
        RECTANGLE, CIRCLE
    }

    private int mMaskColor = 0x80000000;   //暗色
    private int mBorderColor = 0xAA808080; //焦点框的边框颜色
    private int mBorderWidth = 1;         //焦点边框的宽度（画笔宽度）
    private int mFocusWidth = 250;         //焦点框的宽度
    private int mFocusHeight = 250;        //焦点框的高度
    public int mDefaultStyleIndex = 0;    //默认焦点框的形状

    private Style mStyle;
    private final Paint mBorderPaint = new Paint();
    private final Path mFocusPath = new Path();
    private final RectFloat mFocusRect = new RectFloat();

    /******************************** 图片缩放位移控制的参数 ************************************/
    private static final float MAX_SCALE = 4.0f;  //最大缩放比，图片缩放后的大小与中间选中区域的比值
    private static final int NONE = 0;   // 初始化
    private static final int ZOOM_OR_ROTATE = 4;  // 缩放或旋转

    private static final int SAVE_SUCCESS = 1001;  // 缩放或旋转
    private static final int SAVE_ERROR = 1002;  // 缩放或旋转

    private int mImageWidth;
    private int mImageHeight;
    private int mRotatedImageWidth;
    private int mRotatedImageHeight;
    private final Matrix matrix = new Matrix();      //图片变换的matrix
    private final Matrix savedMatrix = new Matrix(); //开始变幻的时候，图片的matrix
    private final Point pA = new Point();          //第一个手指按下点的坐标
    private final Point pB = new Point();          //第二个手指按下点的坐标
    private final Point midPoint = new Point();    //两个手指的中间点
    private Point mFocusMidPoint = new Point();  //中间View的中间点
    private int mode = NONE;            //初始的模式
    private float oldDist = 1;          //双指第一次的距离
    private float mMaxScale = MAX_SCALE;//程序根据不同图片的大小，动态得到的最大缩放比
    private final boolean isInited;   //是否经过了 onSizeChanged 初始化
    private boolean mSaving = false;    //是否正在保存
    private final EventHandler mHandler = new InnerHandler();
    private PixelMap pixelMap;
    private int mPointerIndex1, mPointerIndex2;

    public CropImageView(Context context) {
        this(context, null);

    }

    public CropImageView(Context context, AttrSet attrs) {
        this(context, attrs, null);

    }


    public CropImageView(Context context, AttrSet attrs, String defStyle) {
        super(context, attrs, defStyle);

        mFocusWidth = Utils.vp2px(mFocusWidth, context);
        mFocusHeight = Utils.vp2px(mFocusHeight, context);
        mBorderWidth = Utils.vp2px(mBorderWidth, context);
        isInited = true;

        mMaskColor = ResUtil.getColorValue(attrs, "cropMaskColor", mMaskColor);
        mBorderColor = ResUtil.getColorValue(attrs, "cropBorderColor", mBorderColor);
        mBorderWidth = ResUtil.getDimensionValue(attrs, "cropBorderWidth", mBorderWidth);
        mFocusWidth = ResUtil.getDimensionValue(attrs, "cropFocusWidth", mFocusWidth);
        mFocusHeight = ResUtil.getDimensionValue(attrs, "cropFocusHeight", mFocusHeight);
        mDefaultStyleIndex = ResUtil.getIntValue(attrs, "cropStyle", mDefaultStyleIndex);

        Style[] styles = {Style.RECTANGLE, Style.CIRCLE};
        mStyle = styles[mDefaultStyleIndex];
//        a.recycle();

        setScaleMode(ScaleMode.STRETCH);


        //只允许图片为当前的缩放模式
//        setScaleType(ScaleType.MATRIX);
        setLayoutRefreshedListener(component -> {
            initImage(pixelMap);
            component.addDrawTask((component1, canvas) -> {
                canvas.concat(matrix);
                if (Style.RECTANGLE == mStyle) {
                    Optional<Display>
                            display = DisplayManager.getInstance().getDefaultDisplay(getContext());
                    DisplayAttributes displayAttributes = display.get().getAttributes();

                    mFocusPath.addRect(mFocusRect, Path.Direction.COUNTER_CLOCK_WISE);
                    canvas.save();
                    canvas.clipRect(new RectFloat(0, 0, displayAttributes.width, displayAttributes.height));
                    canvas.clipPath(mFocusPath, Canvas.ClipOp.DIFFERENCE);
                    canvas.drawColor(mMaskColor, Canvas.PorterDuffMode.DST_IN);
                    canvas.restore();
                } else if (Style.CIRCLE == mStyle) {
                    float radius = Math.min((mFocusRect.right - mFocusRect.left) / 2, (mFocusRect.bottom - mFocusRect.top) / 2);

                    mFocusPath.addCircle(mFocusMidPoint.getPointX(), mFocusMidPoint.getPointY(), radius, Path.Direction.COUNTER_CLOCK_WISE);

                    canvas.save();
                    canvas.clipRect(new RectFloat(0, 0, getWidth(), getHeight()));

                    canvas.clipPath(mFocusPath, Canvas.ClipOp.DIFFERENCE);
                    canvas.drawColor(mMaskColor, Canvas.PorterDuffMode.DST_IN);
                    canvas.restore();
                }
                mBorderPaint.setColor(new Color(mBorderColor));
                mBorderPaint.setStyle(Paint.Style.STROKE_STYLE);
                mBorderPaint.setStrokeWidth(mBorderWidth);

                mBorderPaint.setAntiAlias(true);
                canvas.drawPath(mFocusPath, mBorderPaint);
                mFocusPath.reset();
            });
        });
    }


    @Override
    public void setPixelMap(PixelMap pixelMap) {

        super.setPixelMap(pixelMap);
        this.pixelMap = pixelMap;
        initImage(pixelMap);
    }


    @Override
    public void setImageElement(Element element) {

        super.setImageElement(element);
    }

    @Override
    public void setPixelMap(int resId) {

        super.setPixelMap(resId);
    }



    /**
     * 初始化图片和焦点框
     * @param pixelMap  传入PixelMap对象
     */
    private void initImage(PixelMap pixelMap) {

        if (!isInited || pixelMap == null) {

            return;
        }

        mode = NONE;
//        matrix = getImageMatrix();
        mImageWidth = mRotatedImageWidth = pixelMap.getImageInfo().size.width;
        mImageHeight = mRotatedImageHeight = pixelMap.getImageInfo().size.height;

        //计算出焦点框的中点的坐标和上、下、左、右边的x或y的值
        int viewWidth = getWidth();
        int viewHeight = getHeight();
        int midPointX = viewWidth / 2;
        int midPointY = viewHeight / 2;
        mFocusMidPoint = new Point(midPointX, midPointY);

        if (mStyle == Style.CIRCLE) {
            int focusSize = Math.min(mImageWidth, mImageHeight);
            mFocusWidth = focusSize;
            mFocusHeight = focusSize;

        }
        mFocusRect.left = NumCalcUtil.subtract(mFocusMidPoint.getPointX() , mFocusWidth);
        mFocusRect.right = NumCalcUtil.add(mFocusMidPoint.getPointX() , mFocusWidth);
        mFocusRect.top = NumCalcUtil.subtract(mFocusMidPoint.getPointY() , mFocusHeight / 2f);
        mFocusRect.bottom = NumCalcUtil.add(mFocusMidPoint.getPointY() , mFocusHeight / 2f);

        //适配焦点框的缩放比例（图片的最小边不小于焦点框的最小边）
        float fitFocusScale = getScale(mImageWidth, mImageHeight, mFocusWidth, mFocusHeight, true);

        mMaxScale = fitFocusScale * MAX_SCALE;
        //适配显示图片的ImageView的缩放比例（图片至少有一边是铺满屏幕的显示的情形）
        float fitViewScale = getScale(mImageWidth, mImageHeight, viewWidth, viewHeight, false);

        //确定最终的缩放比例,在适配焦点框的前提下适配显示图片的ImageView，
        //方案：首先满足适配焦点框，如果还能适配显示图片的ImageView，则适配它，即取缩放比例的最大值。
        //采取这种方案的原因：有可能图片很长或者很高，适配了ImageView的时候可能会宽/高已经小于焦点框的宽/高
        float scale = Math.max(fitViewScale, fitFocusScale);

        //图像中点为中心进行缩放
        matrix.setScale(scale, scale, mImageWidth / 2f, mImageHeight / 2f);
        setScaleMode(scale == fitViewScale ? ScaleMode.INSIDE : ScaleMode.CENTER);
//        setScale(mImageWidth / 2, mImageHeight / 2);
        float[] mImageMatrixValues = new float[9];
        matrix.getElements(mImageMatrixValues); //获取缩放后的mImageMatrix的值
        float transX = NumCalcUtil.subtract(mFocusMidPoint.getPointX() , (NumCalcUtil.add(mImageMatrixValues[2] , mImageWidth * mImageMatrixValues[0] / 2)));  //X轴方向的位移
        float transY = NumCalcUtil.subtract(mFocusMidPoint.getPointY() , (NumCalcUtil.add(mImageMatrixValues[5] , mImageHeight * mImageMatrixValues[4] / 2))); //Y轴方向的位移

        matrix.postTranslate(transX, transY);
//        setImageMatrix(matrix);
        invalidate();


        if (getTouchEventListener() == null)
            setTouchEventListener((component, event) -> {
//                if (mSaving || null == getImageElement()) {
//                    return super.onTouchEvent(event);
//                }
                switch (event.getAction()) {
                    case TouchEvent.PRIMARY_POINT_DOWN:  //第一个点按下
                        savedMatrix.setMatrix(matrix);   //以后每次需要变换的时候，以现在的状态为基础进行变换
                        pA.modify(event.getPointerPosition(0).getX(), event.getPointerPosition(0).getY());
                        pB.modify(event.getPointerPosition(0).getX(), event.getPointerPosition(0).getY());
                        mPointerIndex1 = event.getPointerId(0);
//                            mode = DRAG;
                        break;
                    case TouchEvent.OTHER_POINT_DOWN:  //第二个点按下
                        int ind = event.getIndex();
                        System.out.println(ind);
                        if (event.getIndex() > 1) break;
                        pA.modify(event.getPointerPosition(0).getX(), event.getPointerPosition(0).getY());
                        pB.modify(event.getPointerPosition(1).getX(), event.getPointerPosition(1).getY());
                        midPoint.modify((NumCalcUtil.add(pA.getPointX() , pB.getPointX())) / 2
                                , (NumCalcUtil.add(pA.getPointY() , pB.getPointY())) / 2);
                        mPointerIndex2 = event.getPointerId(event.getIndex());

                        oldDist = spacing(pA, pB);
                        savedMatrix.setMatrix(matrix);  //以后每次需要变换的时候，以现在的状态为基础进行变换
                        if (oldDist > 10f) mode = ZOOM_OR_ROTATE;//两点之间的距离大于10才有效
                        break;
                    case TouchEvent.POINT_MOVE:
                        if (mode == ZOOM_OR_ROTATE) {
                            int index = event.getIndex();
                            System.out.println(index);
                            float nfX, nfY, nsX, nsY;

                            nsX = event.getPointerPosition(mPointerIndex1).getX();
                            nsY = event.getPointerPosition(mPointerIndex1).getY();
                            int count = event.getPointerCount();
                            System.out.println("count" + count);
                            if (count == 2) {
                                nfX = event.getPointerPosition(mPointerIndex2).getX();
                                nfY = event.getPointerPosition(mPointerIndex2).getY();

                                float newDist = spacing(nsX, nsY, nfX, nfY);
                                if (newDist > 10f) {
                                    matrix.setMatrix(savedMatrix);
                                    // 这里之所以用 maxPostScale 矫正一下，主要是防止缩放到最大时，继续缩放图片会产生位移
                                    float tScale = Math.min(newDist / oldDist, maxPostScale());
                                    if (tScale != 0) {
                                        matrix.postScale(tScale, tScale, midPoint.getPointX(), midPoint.getPointY());
                                        fixScale();
                                        fixTranslation();
//                                        setImageMatrix(matrix);
                                    }
                                }
                            }
                        }
                        break;
                    case TouchEvent.PRIMARY_POINT_UP:
//                            if (mode == DRAG) {
//                                if (spacing(pA, pB) < 50) {
//                                    long now = System.currentTimeMillis();
//                                    if (now - doubleClickTime < 500 && spacing(pA, doubleClickPos) < 50) {
//                                        doubleClick(pA.getPointX(), pA.getPointY());
//                                        now = 0;
//                                    }
//                                    doubleClickPos.modify(pA);
//                                    doubleClickTime = now;
//                                }
//                            }
//                            mode = NONE;
                        break;
                }
                //解决部分机型无法拖动的问题
                invalidate();
//        ViewCompat.postInvalidateOnAnimation(this);
                return true;
            });
    }


    /**
     * 计算边界缩放比例 isMinScale 是否最小比例，true 最小缩放比例， false 最大缩放比例
     * @param bitmapHeight pixelmap高度
     * @param bitmapWidth pixelmap宽度
     * @param isMinScale 是否最小缩放
     * @param min_height 最小高度
     * @param min_width 最小宽度
     * @return 转换比例
     * */
    private float getScale(int bitmapWidth, int bitmapHeight, int min_width, int min_height, boolean isMinScale) {
        float scale;
//        float scaleX = NumCalcUtil.divide(min_width , bitmapWidth);
//        float scaleY = NumCalcUtil.divide(min_height , bitmapHeight);
        float scaleX = (float) min_width / bitmapWidth;
        float scaleY = (float) min_height / bitmapHeight;
        if (isMinScale) {
            scale = Math.max(scaleX, scaleY);
        } else {
            scale = Math.min(scaleX, scaleY);
        }
        return scale;
    }


    /**
     * 修正图片的缩放比
     */
    private void fixScale() {
        float imageMatrixValues[] = new float[9];
        matrix.getElements(imageMatrixValues);
        float currentScale = NumCalcUtil.add(Math.abs(imageMatrixValues[0]) , Math.abs(imageMatrixValues[1]));
        float minScale = getScale(mRotatedImageWidth, mRotatedImageHeight, mFocusWidth, mFocusHeight, true);
        mMaxScale = minScale * MAX_SCALE;

        //保证图片最小是占满中间的焦点空间
        if (currentScale < minScale) {
            float scale = NumCalcUtil.divide(minScale , currentScale);
            matrix.postScale(scale, scale);
            setScale(scale, scale);
        } else if (currentScale > mMaxScale) {
            float scale = NumCalcUtil.divide(mMaxScale , currentScale);
            matrix.postScale(scale, scale);
            setScale(scale, scale);
        }
    }

    /**
     * 修正图片的位移
     */
    private void fixTranslation() {
        RectFloat imageRect = new RectFloat(0, 0, mImageWidth, mImageHeight);
        matrix.mapRect(imageRect);  //获取当前图片（缩放以后的）相对于当前控件的位置区域，超过控件的上边缘或左边缘为负
        float deltaX = 0, deltaY = 0;
        if (imageRect.left > mFocusRect.left) {
            deltaX = NumCalcUtil.add(-imageRect.left , mFocusRect.left);
        } else if (imageRect.right < mFocusRect.right) {
            deltaX = NumCalcUtil.add(-imageRect.right , mFocusRect.right);
        }
        if (imageRect.top > mFocusRect.top) {
            deltaY = NumCalcUtil.add(-imageRect.top , mFocusRect.top);
        } else if (imageRect.bottom < mFocusRect.bottom) {
            deltaY = NumCalcUtil.add(-imageRect.bottom , mFocusRect.bottom);
        }
//        setTranslation(deltaX, deltaY);
        matrix.postTranslate(deltaX, deltaY);
    }

    /**
     * 获取当前图片允许的最大缩放比
     * @return  maxPostScale
     */
    private float maxPostScale() {
        float imageMatrixValues[] = new float[9];
        matrix.getElements(imageMatrixValues);
        float curScale = NumCalcUtil.add(Math.abs(imageMatrixValues[0]) , Math.abs(imageMatrixValues[1]));
        return mMaxScale / curScale;
    }

    /**
     * 计算两点之间的距离
     * @param x1 点1横坐标
     * @param x2 点2横坐标
     * @param y1 点1纵坐标
     * @param y2 点2纵坐标
     * @return 两点之间的距离
     */
    private float spacing(float x1, float y1, float x2, float y2) {
        float x = NumCalcUtil.subtract(x1 , x2);
        float y = NumCalcUtil.subtract(y1 , y2);
        return (float) Math.sqrt(NumCalcUtil.add(x * x , y * y));
    }

    /**
     * 计算两点之间的距离
     * @param pA point a
     * @param pB point b
     * @return 两点之间的距离
     */
    private float spacing(Point pA, Point pB) {
        return spacing(pA.getPointX(), pA.getPointY(), pB.getPointX(), pB.getPointY());
    }

    /**
     * 获取裁剪过的PixelMap
     * @param expectWidth     期望的宽度
     * @param exceptHeight    期望的高度
     * @param isSaveRectangle 是否按矩形区域保存图片
     * @return 裁剪后的Bitmap
     */
    public PixelMap getCropBitmap(int expectWidth, int exceptHeight, boolean isSaveRectangle) {
        if (expectWidth <= 0 || exceptHeight < 0) return null;
//        PixelMap srcBitmap =  getPixelMap();

        //旋转的角度，90的整数倍
        int sumRotateLevel = 0;
        pixelMap = rotate(pixelMap, sumRotateLevel * 90);  //最好用level，因为角度可能不是90的整数
        return makeCropBitmap(pixelMap, mFocusRect, getImageMatrixRect(), expectWidth, exceptHeight, isSaveRectangle);
    }

    /**
     * 对PixelMap进行旋转
     * @param pixelmap 要旋转的图片
     * @param degrees  选择的角度（单位 度）
     * @return 旋转后的Bitmap
     */
    public PixelMap rotate(PixelMap pixelmap, int degrees) {

        if (degrees != 0 && pixelmap != null) {
//            Matrix matrix = new Matrix();
//            matrix.setRotate(degrees, (float) pixelmap.getImageInfo().size.width / 2, (float) pixelmap.getImageInfo().size.height / 2);
            PixelMap.InitializationOptions initOptions = new PixelMap.InitializationOptions();
            Rect rect = new Rect(0, 0, pixelmap.getImageInfo().size.width, pixelmap.getImageInfo().size.height);
            try {
                ImageSource.DecodingOptions options = new ImageSource.DecodingOptions();
                options.rotateDegrees = degrees;
                options.desiredSize.width = pixelmap.getImageInfo().size.width / 2;
                options.desiredSize.height = pixelmap.getImageInfo().size.height / 2;

                PixelMap rotateBitmap = PixelMap.create(pixelmap, rect, initOptions);
//                PixelMap rotateBitmap = PixelMap.create(pixelmap,  matrix, true);

                if (pixelmap != rotateBitmap) {
                    return rotateBitmap;
                }
            } catch (OutOfMemoryError ex) {
                return pixelmap;
            }
        }
        return pixelmap;
    }

    /**
     * 获取图片的MatrixRect
     * @return 获取当前图片显示的矩形区域
     */
    private RectFloat getImageMatrixRect() {
        RectFloat rectF = new RectFloat(0, 0, pixelMap.getImageInfo().size.width, pixelMap.getImageInfo().size.height);
        matrix.mapRect(rectF);
        return rectF;
    }

    /**
     * 裁剪PixelMap
     * @param pixelmap        需要裁剪的图片
     * @param focusRect       中间需要裁剪的矩形区域
     * @param imageMatrixRect 当前图片在屏幕上的显示矩形区域
     * @param expectWidth     希望获得的图片宽度，如果图片宽度不足时，拉伸图片
     * @param exceptHeight    希望获得的图片高度，如果图片高度不足时，拉伸图片
     * @param isSaveRectangle 是否希望按矩形区域保存图片
     * @return 裁剪后的图片的Bitmap
     */
    private PixelMap makeCropBitmap(PixelMap pixelmap, RectFloat focusRect, RectFloat imageMatrixRect, int expectWidth, int exceptHeight, boolean isSaveRectangle) {
        if (imageMatrixRect == null || pixelmap == null) {
            return null;
        }
        float scale = imageMatrixRect.getWidth() / pixelmap.getImageInfo().size.width;
        int left = (int) ((focusRect.left - imageMatrixRect.left) / scale);
        int top = (int) ((focusRect.top - imageMatrixRect.top) / scale);
        int width = (int) (focusRect.getWidth() / scale);
        int height = (int) (focusRect.getHeight() / scale);

        if (left < 0) left = 0;
        if (top < 0) top = 0;
        if (left + width > pixelmap.getImageInfo().size.width) width = pixelmap.getImageInfo().size.width - left;
        if (top + height > pixelmap.getImageInfo().size.height) height = pixelmap.getImageInfo().size.height - top;

        try {
            PixelMap.InitializationOptions options = new PixelMap.InitializationOptions();
            Rect rect = new Rect(left, top, width, height);
            pixelmap = PixelMap.create(pixelmap, rect, options);
            if (expectWidth != width || exceptHeight != height) {
                options.size.height = exceptHeight;
                options.size.width = expectWidth;
                options.useSourceIfMatch = true;

                pixelmap = PixelMap.create(pixelmap, options);

                if (mStyle == CropImageView.Style.CIRCLE && !isSaveRectangle) {

                    //如果是圆形，就将图片裁剪成圆的
                    int length = Math.min(expectWidth, exceptHeight);
                    int radius = length / 2;
                    options.size.width = length;
                    options.size.height = length;
                    options.pixelFormat = PixelFormat.ARGB_8888;
                    PixelMap circleBitmap = PixelMap.create(options);
                    Texture texture = new Texture(circleBitmap);
                    Canvas canvas = new Canvas(texture);
                    PixelMapHolder holder = new PixelMapHolder(pixelmap);
                    PixelMapShader bitmapShader = new PixelMapShader(holder, PixelMapShader.TileMode.CLAMP_TILEMODE, Shader.TileMode.CLAMP_TILEMODE);
                    Paint paint = new Paint();
                    paint.setShader(bitmapShader, Paint.ShaderType.PIXELMAP_SHADER);
                    canvas.drawCircle(expectWidth / 2f, exceptHeight / 2f, radius, paint);
                    pixelmap = texture.getPixelMap();
                }
            }
        } catch (OutOfMemoryError e) {
            return pixelmap;
        }
        return pixelmap;
    }

    /**
     * 保存PixelMap到文件
     * @param folder          希望保存的文件夹
     * @param expectWidth     希望保存的图片宽度
     * @param exceptHeight    希望保存的图片高度
     * @param isSaveRectangle 是否希望按矩形区域保存图片
     */
    public void saveBitmapToFile(File folder, int expectWidth, int exceptHeight, boolean isSaveRectangle) {
        if (mSaving) return;
        mSaving = true;
        final PixelMap croppedImage = getCropBitmap(expectWidth, exceptHeight, isSaveRectangle);
        ImagePacker.PackingOptions options = new ImagePacker.PackingOptions();
        options.format = "image/jpeg";
        final File finalSaveFile = createFile(folder, "IMG_", ".jpg");
        new Thread() {
            @Override
            public void run() {
                saveOutput(croppedImage, options, finalSaveFile);
            }
        }.start();
    }

    /**
     * 根据系统时间、前缀、后缀产生一个文件
     * @param suffix suffix
     * @param prefix prefix
     * @param folder folder
     * @return file file
     */
    private File createFile(File folder, String prefix, String suffix) {
        if (!folder.exists() || !folder.isDirectory()){
            boolean mkdirs = folder.mkdirs();
        }
        try {
            File nomedia = new File(folder, ".nomedia");  //在当前文件夹底下创建一个 .nomedia 文件
            if (!nomedia.exists()){
                boolean create = nomedia.createNewFile();
                if(create){
                   System.out.println();
                }
            }
        } catch (IOException e) {
            return new File(folder, "filename");
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA);
        String filename = prefix + dateFormat.format(new Date(System.currentTimeMillis())) + suffix;
        return new File(folder, filename);
    }

    /**
     * 将图片保存在本地
     * @param croppedImage 被裁减的PixelMap
     * @param outputFormat 输出rgb格式
     * @param saveFile 存储目标文件
     */
    private void saveOutput(PixelMap croppedImage, ImagePacker.PackingOptions outputFormat, File saveFile) {
        FileOutputStream outputStream = null;
        ImagePacker imagePacker = ImagePacker.create();
        try {
            outputStream = new FileOutputStream(saveFile);
//            outputStream = getContext().getContentResolver().openOutputStream(Uri.getUriFromFile(saveFile));
            if (outputStream != null) {
                outputFormat.quality = 90;
                imagePacker.initializePacking(outputStream, outputFormat);
                imagePacker.addImage(croppedImage);
                imagePacker.finalizePacking();

//                croppedImage.compress(outputFormat, 90, outputStream);
            }
            mHandler.sendEvent(InnerEvent.get(SAVE_SUCCESS, saveFile));
        } catch (IOException ex) {
            mHandler.sendEvent(InnerEvent.get(SAVE_ERROR, saveFile));
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    mHandler.sendEvent(InnerEvent.get(SAVE_ERROR, saveFile));
                }
            }
        }
        mSaving = false;
        croppedImage.release();
    }

    private class InnerHandler extends EventHandler {
        public InnerHandler() {
            super(EventRunner.getMainEventRunner());
        }

        @Override
        public void sendEvent(InnerEvent event) throws IllegalArgumentException {
            File saveFile = (File) event.object;
            switch (event.eventId) {
                case SAVE_SUCCESS:
                    if (mListener != null) mListener.onBitmapSaveSuccess(saveFile);
                    break;
                case SAVE_ERROR:
                    if (mListener != null) mListener.onBitmapSaveError(saveFile);
                    break;
            }
        }
    }

    /**
     * 图片保存完成的监听
     */
    private OnBitmapSaveCompleteListener mListener;

    public interface OnBitmapSaveCompleteListener {
        void onBitmapSaveSuccess(File file);

        void onBitmapSaveError(File file);
    }

    /**
     * 设置图片保存成功的回调
     * @param listener listener
     */
    public void setOnBitmapSaveCompleteListener(OnBitmapSaveCompleteListener listener) {
        mListener = listener;
    }

    /**
     * 设置焦点框的宽度
     * @param width 焦点宽度
     */
    public void setFocusWidth(int width) {
        mFocusWidth = width;
        initImage(this.pixelMap);
    }

    /**
     * 设置焦点框的高度
     * @param height 焦点框高度
     */
    public void setFocusHeight(int height) {
        mFocusHeight = height;
        initImage(this.pixelMap);
    }

    /**
     * 设置焦点框的形状
     * @param style focusStyle
     */
    public void setFocusStyle(Style style) {
        this.mStyle = style;
        invalidate();
    }
}